package cn.bubi.access.utils;

import cn.bubi.access.utils.spring.StringUtils;

public abstract class PathUtils{

    public static final String PATH_SEPERATOR = "/";
    public static final char PATH_SEPERATOR_CHAR = '/';

    public static final String WINDOWS_PATH_SEPERATOR = "\\";

    public static final String SCHEMA_SEPERATOR = ":";

    /**
     * 标准化指定的路径；
     * <p>
     * 标准化的过程包括：
     * 1、清理字符串中的 ".";
     * 2、清除字符串中的 ".."以及路径中相应的上一级路径；(例如：ab/../cd 处理后变为 cd )
     * 2、将 windows 的分隔符"\"替换为标准分隔符"/"；
     * 3、将连续重复的分隔符替换为单个分隔符；
     * 4、去除结尾的分隔符；
     * 5、去除其中的空白字符；
     * <p>
     * 注：以冒号":"分隔的 schema 头将被保留；
     *
     * @param path
     * @return
     */
    public static String standardize(String path){
        path = StringUtils.trimAllWhitespace(path);
        path = StringUtils.cleanPath(path);
        path = cleanRepeatlySeperator(path);
        if (path.endsWith(PATH_SEPERATOR)) {
            return path.substring(0, path.length() - 1);
        }
        return path;
    }

    /**
     * 将指定的路径转换为绝对路径；
     * <p>
     * 方法将检测指定的路径如果既没有以路径分隔符"/"开头，也没有冒号":"分隔的 schema 开头(例如 file:)，
     * <p>
     * 则在开头加上路径分隔符"/"返回；
     * <p>
     * 注：方法不会检测路径是否标准，也不会自动将其标准化；
     *
     * @param path
     * @return
     */
    public static String absolute(String path){
        if (path.startsWith(PATH_SEPERATOR)) {
            return path;
        }
        if (path.indexOf(SCHEMA_SEPERATOR) >= 0) {
            return path;
        }
        return PATH_SEPERATOR + path;
    }

    /**
     * 清除路径中的重复分隔符；
     *
     * @param path
     * @return
     */
    public static String cleanRepeatlySeperator(String path){
        // 去除重复的分隔符；
        String schema = "";
        String pathToProcess = path;
        int index = path.indexOf("://");
        if (index >= 0) {
            schema = path.substring(0, index + 3);
            for (index = index + 3; index < path.length(); index++) {
                if (path.charAt(index) != PATH_SEPERATOR_CHAR) {
                    break;
                }
            }
            pathToProcess = path.substring(index);
        }
        StringBuilder pathToUse = new StringBuilder();
        boolean hit = false;
        char ch;
        for (int i = 0; i < pathToProcess.length(); i++) {
            ch = pathToProcess.charAt(i);
            if (ch == PATH_SEPERATOR_CHAR) {
                if (hit) {
                    continue;
                } else {
                    hit = true;
                }
            } else {
                hit = false;
            }
            pathToUse.append(ch);
        }
        return schema + pathToUse;
    }

    /**
     * @param paths
     */
    public static String concatPaths(String... paths){
        if (paths == null || paths.length == 0) {
            return "";
        }
        StringBuilder path = new StringBuilder();
        for (String p : paths) {
            path.append(p);
            path.append(PATH_SEPERATOR_CHAR);
        }
        return standardize(path.toString());
    }
}
